package de.tum.in.elitese.wahlsys.persister;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import javax.swing.JOptionPane;

import de.tum.in.elitese.wahlsys.common.DbProperties;

/**
 * This Class is the PersistenceComponent. It is responsible for persisting the
 * PersistanceObjects.
 * 
 * @author Christoph Frenzel
 */
public class Persister {

	private static int maxBatchCount = 0;

	/**
	 * This method writes the given List of PersistenceObjects into the data
	 * base.
	 * 
	 * @param persistenceObjectList
	 *            the List of PersistenceObject to be saved
	 */
	public static void persist(List<? extends PersistenceObject> persistenceObjectList) {
		if (persistenceObjectList == null) {
			throw new IllegalArgumentException("persistenceObjectList must not be null");
		}

		// depending on the data base system and the driver there is a maximum
		// number of atomic updates within a batch update. This number can be
		// configured in the wahlsystem.properties file.
		if (maxBatchCount < 1) {
			try {
				String tempMaxBatchCount = DbProperties.getProperty(DbProperties.MAX_BATCH_COUNT);
				maxBatchCount = Integer.valueOf(tempMaxBatchCount);
				if (maxBatchCount < 1) {
					throw new NumberFormatException();
				}
			} catch (NumberFormatException e) {
				// this is not a stopping exception. Thus there is no error
				// dialog for this
				System.err.println("Property for max_batch_count could not be read. The default of 1000 will be used.");
				e.printStackTrace();
				// set a save value
				maxBatchCount = 1000;
			}
		}

		Statement sql_stmt = null;
		Connection conn = null;

		// load driver
		try {
			Class.forName(DbProperties.getProperty(DbProperties.DRIVER));
		} catch (ClassNotFoundException e) {
			JOptionPane.showMessageDialog(null, "Database Driver could not be found. Please check the classpath.", "Database Driver could not be found.", JOptionPane.ERROR_MESSAGE);
			e.printStackTrace();
			System.exit(-1);
		}

		// set up connection
		try {
			conn = DriverManager.getConnection(DbProperties.getProperty(DbProperties.URL), DbProperties.getProperties());
		} catch (SQLException e) {
			JOptionPane.showMessageDialog(null, "Could not establish connection to the data base. Please verify the url, username and password.", "Could not establish connection to the data base.",
					JOptionPane.ERROR_MESSAGE);
			e.printStackTrace();
			System.exit(-1);
		}

		// do inserts
		try {
			conn.setAutoCommit(false);

			int batchcount = 0;
			sql_stmt = conn.createStatement();
			// add insert statements to the batch update
			for (PersistenceObject persistanceObject : persistenceObjectList) {
				for (String string : persistanceObject.getPersistanceStrings()) {
					sql_stmt.addBatch(string);
					batchcount++;
					// check whether the maximum batch count is reached an
					// run the batch.
					if (batchcount > maxBatchCount) {
						sql_stmt.executeBatch();
						batchcount = 0;
					}
				}
			}
			// run the batch if neccessary
			if (batchcount > 0) {
				sql_stmt.executeBatch();
			}
			conn.commit();
		} catch (SQLException e) {
			JOptionPane.showMessageDialog(null, "An Exception occured while saving the data. The message of the Exception is:\n" + e.getLocalizedMessage(),
					"An Exception occured while saving the data.", JOptionPane.ERROR_MESSAGE);
			e.printStackTrace();

			try {
				// rollback
				conn.rollback();
			} catch (SQLException e1) {
				JOptionPane.showMessageDialog(null, "The changes could not be rolled back. The message of the Exception is:\n" + e.getLocalizedMessage(), "The changes could not be rolled back.",
						JOptionPane.ERROR_MESSAGE);
				e.printStackTrace();
			}
			System.exit(-1);
		} finally {
			try {
				conn.close();
			} catch (SQLException e) {
				JOptionPane.showMessageDialog(null, "The Connection to the data base could not be closed. The message of the Exception is:\n" + e.getLocalizedMessage(),
						"The Connection to the data base could not be closed.", JOptionPane.ERROR_MESSAGE);
				e.printStackTrace();
				System.exit(-1);
			}
		}
	}
}
